from collections import deque
class AVLNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None
        self.parent = None
        self.bf = 0


class AVLTree:
    def __init__(self, li=None):
        self.root = None
        if li:
            for val in li:
                self.insert_no_rec(val)

    def is_empty(self):
        return self.root == None

    def search_no_rec(self, val):
        p = self.root
        while p:
            if val < p.data:
                p = p.lchild
            elif val > p.data:
                p = p.rchild
            else:
                return p
        return None

    def rotate_left(self, p, c):
        s2 = c.lchild
        p.rchild = s2
        if s2:
            s2.parent = p
        c.lchild = p
        p.parent = c
        p.bf = 0
        c.bf = 0
        return c

    def rotate_left_1(self, p, c):
        s2 = c.lchild
        p.rchild = s2
        if s2:
            s2.parent = p
        c.lchild = p
        p.parent = c
        if c.bf == 0:
            p.bf = 1
            c.bf = -1
        else:
            p.bf = 0
            c.bf = 0
        return c

    def rotate_right(self, p, c):
        s2 = c.rchild
        p.lchild = s2
        if s2:
            s2.parent = p
        c.rchild = p
        p.parent = c
        c.bf = 0
        p.bf = 0
        return c

    def rotate_right_1(self, p, c):
        s2 = c.rchild
        p.lchild = s2
        if s2:
            s2.parent = p
        c.rchild = p
        p.parent = c
        if c.bf == 0:
            p.bf = -1
            c.bf = 1
        return c

    def rotate_right_left(self, p, c):
        g = c.lchild
        s3 = g.rchild
        c.lchild = s3
        if s3:
            s3.parent = c
        g.rchild = c
        c.parent = g

        s2 = g.lchild
        p.rchild = s2
        if s2:
            s2.parent = p
        g.lchild = p
        p.parent = g

        if g.bf > 0:
            p.bf = -1
            c.bf = 0

        elif g.bf < 0:
            p.bf = 0
            c.bf = 1
        else:
            p.bf = 0
            c.bf = 0
        g.bf = 0
        return g

    def rotate_left_right(self, p, c):
        g = c.rchild
        s2 = g.lchild
        c.rchild = s2
        if s2:
            s2.parent = c
        g.lchild = c
        c.parent = g

        s3 = g.rchild
        p.lchild = s3
        if s3:
            s3.parent = p
        g.rchild = p
        p.parent = g

        if g.bf > 0:
            c.bf = -1
            p.bf = 0
        elif g.bf < 0:
            c.bf = 0
            p.bf = 1
        else:
            p.bf = 0
            c.bf = 0
        g.bf = 0
        return g

    def insert_no_rec(self, val):
        p = self.root
        if not p:
            self.root = AVLNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:
                    p = p.lchild
                else:
                    p.lchild = AVLNode(val)
                    p.lchild.parent = p
                    node = p.lchild  # node为当前插入的节点
                    break
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:
                    p.rchild = AVLNode(val)
                    p.rchild.parent = p
                    node = p.rchild  # node为当前插入的节点
                    break
            else:
                return

        # 更新balance factor
        while node.parent:
            if node == node.parent.lchild:  # 传递从左子树来的
                if node.parent.bf < 0:
                    g = node.parent.parent  # 连接旋转后的子树
                    x = node.parent
                    if node.bf > 0:
                        n = self.rotate_left_right(node.parent, node)
                    else:
                        n = self.rotate_right(node.parent, node)
                elif node.parent.bf > 0:
                    node.parent.bf = 0
                    break
                else:
                    node.parent.bf = -1
                    node = node.parent
                    continue
            else:  # 传递从右子树来的
                if node.parent.bf > 0:
                    g = node.parent.parent
                    x = node.parent
                    if node.bf > 0:
                        n = self.rotate_left(node.parent, node)
                    elif node.bf < 0:
                        n = self.rotate_right_left(node.parent, node)
                elif node.parent.bf < 0:
                    node.parent.bf = 0
                    break
                else:
                    node.parent.bf = 1
                    node = node.parent
                    continue
            n.parent = g
            if g:
                if x == g.lchild:
                    g.lchild = n
                else:
                    g.rchild = n
                break
            else:
                self.root = n
                break
    def delete(self, val):
        def updata_bf_rec(node):
            if node == self.root:
                return
            if node == node.parent.lchild:
                if node.parent.bf >=0:
                    node.parent.bf += 1
                    return
                else:
                    node.parent.bf = 0
                    updata_bf_rec(node.parent)
            else:
                if node.parent.bf <= 0:
                    node.parent.bf -= 1
                    return
                else:
                    node.parent.bf = 0
                    updata_bf_rec(node.parent)

        def update_bf(node):
            if node == node.parent.lchild:  # 删除左边节点
                while node.parent.bf == -1 and node.parent != self.root:
                    node.parent.bf = 0
                    node = node.parent
                node.parent.bf += 1
            elif node == node.parent.rchild:
                while node.parent.bf == 1 and node.parent != self.root:
                    node.parent.bf = 0
                    node = node.parent
                node.parent.bf -= 1

        def remove_leaf(node):
            updata_bf_rec(node)
            if node == node.parent.lchild:
                node.parent.lchild = None
            else:
                node.parent.rchild = None
            node = node.parent
            print('node', node.data)
            print('node', node.bf)
            print('node.parent', node.parent.data)
            print('node.parent', node.parent.bf)
            while node != self.root and node.bf in (0, -1, 1):
                node = node.parent
            z = node
            print('z',z.data)
            print('z',z.bf)
            if z == self.root and z.bf in (-1, 0, 1):
                return
            g = z.parent
            temp = z
            if z.bf >= 0:
                y = z.rchild
            else:
                y = z.lchild
            if y.bf >= 0:
                x = y.rchild
            else:
                x = y.lchild
            if y == z.lchild:
                if x == y.lchild:
                    n = self.rotate_right(z, y)
                else:
                    n = self.rotate_left_right(z, y)
            else:
                if x == y.lchild:
                    n = self.rotate_right_left(z, y)
                else:
                    n = self.rotate_left_1(z, y)
            print('x',x.data)
            print('y',y.data)
            n.parent = g
            if g:
                if temp == g.lchild:
                    g.lchild = n
                else:
                    g.rchild = n
            else:
                self.root = n

        node = self.search_no_rec(val)
        if not node:  # 无此节点
            return
        if not node.lchild and not node.rchild:  #leaf
            print(111)
            remove_leaf(node)
        elif not node.rchild:  #have left child
            print(222)
            node.data = node.lchild.data
            remove_leaf(node.lchild)
        elif not node.lchild:  #have right child
            print(333)
            node.data = node.rchild.data
            remove_leaf(node.rchild)
        else:
            print(444)
            p = node.rchild
            while p.lchild:
                p = p.lchild
            node.data = p.data
            if not p.rchild:
                remove_leaf(p)
            else:
                p.data = p.rchild.data
                remove_leaf(p.rchild)


    def pre_order(self,root):
        if root:
            print(root.data, end=',')
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)

    def in_order(self, root):
        if root:
            self.in_order(root.lchild)
            print(root.data, end=',')
            self.in_order(root.rchild)

    def post_order(self, root):
        if root:
            self.post_order(root.lchild)
            self.post_order(root.rchild)
            print(root.data, end=',')

    def level_order(self,root):
        queue = deque()
        queue.append(root)
        while len(queue) > 0:
            node = queue.popleft()
            print(node.data,node.bf, end=',')
            if node.lchild:
                queue.append(node.lchild)
            if node.rchild:
                queue.append(node.rchild)